package com.hmkj.web.controller.pay;

import com.hmkj.common.entity.ResultEntity;
import com.hmkj.common.utils.BigDecimalUtils;
import com.hmkj.common.utils.OrderNoUtils;
import com.hmkj.common.utils.StringUtils;
import com.hmkj.common.utils.ValidateUtils;
import com.hmkj.core.api.umf.UmfEndPoint;
import com.hmkj.core.api.umf.domain.ResultCode;
import com.hmkj.core.api.umf.domain.UmfCommon;
import com.hmkj.core.constant.ConfigNID;
import com.hmkj.core.constant.Constants;
import com.hmkj.core.exception.BussinessException;
import com.hmkj.core.po.amount.Cash;
import com.hmkj.core.po.amount.Recharge;
import com.hmkj.core.po.user.User;
import com.hmkj.core.po.user.UserFreeze;
import com.hmkj.core.service.amount.AccountService;
import com.hmkj.core.service.amount.CashService;
import com.hmkj.core.service.amount.RechargeService;
import com.hmkj.core.service.system.ConfigureService;
import com.hmkj.core.service.user.UserFreezeService;
import com.hmkj.core.service.user.UserService;
import com.hmkj.web.controller.GenericController;
import com.umpay.api.common.ReqData;
import com.umpay.api.exception.ReqDataException;
import com.umpay.api.exception.RetDataException;
import com.umpay.api.paygate.v40.Mer2Plat_v40;
import com.umpay.api.paygate.v40.Plat2Mer_v40;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Created by 陌上人 on 2077/7/7 16:20.
 * 联动优势支付接口
 */
@Api(description = "联动优势支付接口相关")
@Slf4j
@RestController
@RequestMapping(GenericController.MEMBER_URL + "/pay/umpay")
public class UmpayController extends GenericController<Integer, Recharge> {

    @Autowired
    ConfigureService configureService;

    @Autowired
    AccountService accountService;

    @Autowired
    RechargeService rechargeService;

    @Autowired
    CashService cashService;

    @Autowired
    UserService userService;

    @Autowired
    UserFreezeService userFreezeService;

    @ApiOperation(value = "联动优势h5收银台接口", notes = "联动优势h5收银台接口")
    @ResponseBody
    @RequestMapping(value = "h5pay", method = RequestMethod.POST)
    public ResultEntity h5pay(@ApiParam("充值金额") @RequestParam String amount) {
        User user = getLoginUser();
        if (StringUtils.isBlank(user.getRealName())) {
            throw new BussinessException("请先通过实名认证");
        }
        //校验用户充值是否冻结
        UserFreeze userFreeze = userFreezeService.selectOne(new UserFreeze(f ->{
            f.setDelFlag(UserFreeze.DELFLAG.NORMAL.code);
            f.setUserId(user.getId());
        }));
        if(null == userFreeze || UserFreeze.STATUS.T1.code != userFreeze.getFreezeRecharge()){
            throw new BussinessException("您的账户充值功能已被冻结，请联系客服处理");
        }

        if (StringUtils.isBlank(amount) || Constants.CONS_ZERO.equals(amount)) {
            throw new BussinessException("请输入充值金额");
        }

        if (!ValidateUtils.isMoney(amount)) {
            throw new BussinessException("输入的金额不合法");
        }

        //构建请求参数
        Map<String, String> params = new HashMap<>(30);
        //接口名称
        params.put("service", UmfEndPoint.service_h5_pay);
        params.put("charset", "UTF-8");
        //商户编号
        params.put("mer_id", UmfEndPoint.MERCHANT_ID);
        params.put("sign_type", "RSA");
        //服务器异步通知地址  configureService.getByNid(ConfigNID.WEB_SERVER_URL)
        params.put("notify_url", "http://bingsss.tunnel.echomod.cn" + GenericController.BASE_API_URL + "/pay/payResultNotify");
        //TODO 服务器同步通知地址 该地址需要后台配置
        params.put("ret_url", redisService.get(ConfigNID.PAY_RETURN_URL));
        //响应数据格式
        params.put("res_format", "HTML");
        params.put("version", "4.0");
        String orderId = OrderNoUtils.getRechargeOrderNo();
        params.put("order_id", orderId);
        params.put("mer_date", DateFormatUtils.format(new Date(), "yyyyMMdd"));
        //金额以分为单位 所以这里乘以100
        params.put("amount", BigDecimalUtils.mul(new BigDecimal(amount), 100d).intValue() + "");
        params.put("amt_type", "RMB");
        //商品号 这里用用户 'SP' + id 作为商品编号
        params.put("goods_id", "SP" + user.getId());
        params.put("goods_inf", "iphone8 64G");
        //支付卡号
        params.put("card_id", "");
        //证件类型 身份证 1  （证件类型、证件号码需同时传有值或者同时不传）
        params.put("identity_type", "");
        //证件号  （证件类型、证件号码需同时传有值或者同时不传）
        params.put("identity_code", "");
        //持卡人姓名
        params.put("card_holder", "");
        //商户用户标识 其实就是userId
        params.put("mer_cust_id", user.getId().toString());
        //商户私有域
        params.put("mer_priv", "");
        params.put("user_ip", "");
        params.put("expand", "");
        params.put("expire_time", "1440");
        params.put("risk_expand", "");
        //是否允许用户修改支付要素 如果传入card_id、card_holder和卡号，是否允许用户在联动平台上修改. 0：不允许修改
        params.put("can_modify_flag", "0");
        //分账类别 2 标准分账
        params.put("split_category", "");
        //分账类型  11：立即分账 21：延时分账
        params.put("split_type", "");
        params.put("split_data", "");

        String payUrl = UmfEndPoint.generateH5PayHtml(params);
        if (StringUtils.isNotBlank(payUrl)) {
            if (rechargeService.createOrder(user, amount, orderId)) {
                params.clear();
                params.put("payUrl",payUrl);
                return ok("支付链接生成成功", params);
            }
            return fail("订单生成失败");
        } else {
            return fail("支付链接生成失败");
        }
    }

    @ApiOperation(value = "联动优势协议支付接口", notes = "联动优势协议支付接口")
    @ResponseBody
    @RequestMapping(value = "protocolPay", method = RequestMethod.POST)
    public ResultEntity protocolPay(@ApiParam("充值金额") @RequestParam String amount,
                                    @ApiParam("支付协议号") @RequestParam String usrPayAgreementId) {
        User user = getLoginUser();
        if (StringUtils.isBlank(user.getRealName())) {
            throw new BussinessException("请先通过实名认证");
        }
        //校验用户充值是否冻结
        UserFreeze userFreeze = userFreezeService.selectOne(new UserFreeze(f ->{
            f.setDelFlag(UserFreeze.DELFLAG.NORMAL.code);
            f.setUserId(user.getId());
        }));
        if(null == userFreeze || UserFreeze.STATUS.T1.code != userFreeze.getFreezeRecharge()){
            throw new BussinessException("您的账户充值功能已被冻结，请联系客服处理");
        }

        if (StringUtils.isBlank(usrPayAgreementId)) {
            throw new BussinessException("支付协议号不能为空");
        }

        if (StringUtils.isBlank(amount) || Constants.CONS_ZERO.equals(amount)) {
            throw new BussinessException("请输入充值金额");
        }

        if (!ValidateUtils.isMoney(amount)) {
            throw new BussinessException("输入的金额不合法");
        }

        //构建请求参数
        Map<String, String> params = new HashMap<>(30);
        //接口名称
        params.put("service", UmfEndPoint.service_h5_pay);
        params.put("charset", "UTF-8");
        //商户编号
        params.put("mer_id", UmfEndPoint.MERCHANT_ID);
        params.put("sign_type", "RSA");
        //服务器异步通知地址  configureService.getByNid(ConfigNID.WEB_SERVER_URL)
        params.put("notify_url", "http://otc-futures.tunnel.echomod.cn" + GenericController.BASE_API_URL + "/pay/payResultNotify");
        //TODO 服务器同步通知地址 该地址需要后台配置
        params.put("ret_url", redisService.get(ConfigNID.PAY_RETURN_URL));
        //响应数据格式
        params.put("res_format", "HTML");
        params.put("version", "4.0");
        String orderId = OrderNoUtils.getRechargeOrderNo();
        params.put("order_id", orderId);
        params.put("mer_date", DateFormatUtils.format(new Date(), "yyyyMMdd"));
        //金额以分为单位 所以这里乘以100
        params.put("amount", BigDecimalUtils.mul(new BigDecimal(amount), 100d).intValue() + "");
        params.put("amt_type", "RMB");
        //商品号 这里用用户 'SP' + id 作为商品编号
        params.put("goods_id", "SP" + user.getId());
        params.put("goods_inf", "iphone8 64G");
        //商户用户标识 其实就是userId
        params.put("mer_cust_id", user.getId().toString());
        //支付协议号
        params.put("usr_pay_agreement_id", usrPayAgreementId);
        //商户私有域
        params.put("mer_priv", "");
        params.put("user_ip", "");
        params.put("expand", "");
        params.put("expire_time", "1440");
        params.put("risk_expand", "");
        //是否允许用户修改支付要素 如果传入card_id、card_holder和卡号，是否允许用户在联动平台上修改. 0：不允许修改
        params.put("can_modify_flag", "0");
        //分账类别 2 标准分账
        params.put("split_category", "");
        //分账类型  11：立即分账 21：延时分账
        params.put("split_type", "");
        params.put("split_data", "");

        String payHtml = UmfEndPoint.generateH5PayHtml(params);
        if (StringUtils.isNotBlank(payHtml)) {
            if (rechargeService.createOrder(user, amount, orderId)) {
                params.clear();
                params.put("payHtml", payHtml);
                return ok("h5支付接口参数生成功能", params);
            }
            return fail("订单生成失败");
        } else {
            return fail("支付链接生成失败");
        }
    }

    @ApiOperation(value = "联动优势商户支持的银行列表", notes = "联动优势商户支持的银行列表")
    @ResponseBody
    @RequestMapping(value = "queryMerBankShortcut", method = RequestMethod.POST)
    public ResultEntity queryMerBankShortcut() {
        //构建请求参数
        Map<String, Object> params = new HashMap<>(30);
        //接口名称
        params.put("service", UmfEndPoint.service_mer_bank_shortcut);
        params.put("charset", "UTF-8");
        //商户编号
        params.put("mer_id", UmfEndPoint.MERCHANT_ID);
        params.put("sign_type", "RSA");
        params.put("version", "4.0");
        params.put("res_format", "HTML");
        params.put("pay_type", "DEBITCARD");
        ReqData reqData;
        Map resData = new HashMap(10);
        try {
            //生成post请求对象
            reqData = Mer2Plat_v40.makeReqDataByPost(params);

            String resDataStr = UmfEndPoint.queryMerCustBankShortcut(params, reqData);
            if (StringUtils.isNotBlank(resDataStr)) {
                resData = Plat2Mer_v40.getResData(resDataStr);
            }

            if (resData.get(UmfCommon.RET_CODE).equals(ResultCode.RESULT_CODE_OK)) {
                return ok(resData.get(UmfCommon.RET_MSG).toString(), resData.get(UmfCommon.MER_BANK_LIST));
            } else {
                return fail(resData.get(UmfCommon.RET_MSG).toString());
            }
        } catch (ReqDataException | RetDataException e) {
            e.printStackTrace();
            return fail("接口调用异常,请查看日志");
        }
    }

    @ApiOperation(value = "联动优势用户已签约的银行列表", notes = "联动优势用户已签约的银行列表")
    @ResponseBody
    @RequestMapping(value = "queryMerCustBankShortcut", method = RequestMethod.POST)
    public ResultEntity queryMerCustBankShortcut() {
        //构建请求参数
        Map<String, Object> params = new HashMap<>(30);
        //接口名称
        params.put("service", UmfEndPoint.service_mer_cust_bank_shortcut);
        params.put("charset", "UTF-8");
        //商户编号
        params.put("mer_id", UmfEndPoint.MERCHANT_ID);
        params.put("sign_type", "RSA");
        params.put("version", "4.0");
        params.put("res_format", "HTML");
        params.put("pay_type", "DEBITCARD");
        params.put("mer_cust_id", getLoginUser().getId() + "");
        ReqData reqData;
        Map resData = new HashMap(10);
        try {
            //生成post请求对象
            reqData = Mer2Plat_v40.makeReqDataByPost(params);

            String resDataStr = UmfEndPoint.queryMerCustBankShortcut(params, reqData);
            if (StringUtils.isNotBlank(resDataStr)) {
                resData = Plat2Mer_v40.getResData(resDataStr);
            }

            if (resData.get(UmfCommon.RET_CODE).equals(ResultCode.RESULT_CODE_OK)) {
                return ok(resData.get(UmfCommon.RET_MSG).toString(), resData.get(UmfCommon.BANK_LIST));
            } else {
                return fail(resData.get(UmfCommon.RET_MSG).toString());
            }
        } catch (ReqDataException | RetDataException e) {
            e.printStackTrace();
            return fail("接口调用异常,请查看日志");
        }
    }

    @ApiOperation(value = "用户提现接口", notes = "用户提现")
    @ResponseBody
    @RequestMapping(value = "doFuKuan", method = RequestMethod.POST)
    public ResultEntity doFuKuan(@ApiParam("提现金额") @RequestParam String amount,
                                 @ApiParam("用户提现银行卡id") @RequestParam Integer bankId) {
        User user = getLoginUser();
        if (StringUtils.isBlank(user.getRealName())) {
            throw new BussinessException("请先通过实名认证");
        }
        //校验用户充值是否冻结
        UserFreeze userFreeze = userFreezeService.selectOne(new UserFreeze(f ->{
            f.setDelFlag(UserFreeze.DELFLAG.NORMAL.code);
            f.setUserId(user.getId());
        }));
        if(null == userFreeze || UserFreeze.STATUS.T1.code != userFreeze.getFreezeCash()){
            throw new BussinessException("您的账户提现功能已被冻结，请联系客服处理");
        }
        if (StringUtils.isBlank(amount) || Constants.CONS_ZERO.equals(amount)) {
            throw new BussinessException("请输入提现金额");
        }
        if (!ValidateUtils.isMoney(amount)) {
            throw new BussinessException("输入的金额不合法");
        }
        Map<String,String> result =  cashService.doCash(user,bankId,new BigDecimal(amount), GenericController.BASE_API_URL);
        if(Integer.valueOf(result.get("needAudit")).intValue()==Cash.NEEDAUDIT.T1.code){
            return ok(result.get("resMsg"),null);
        }else{
            return ok(result.get("resMsg"),null);
        }
    }
}
